#include <QDebug>

#include "basemodel.h"
#include "baseview.h"
#include "basecontroller.h"

#include "core/customermodel.h"

/*
  Returns the controller for this view. If no controller has
  been set yet, this returns NULL.
 */
BaseController *BaseView::getController()
{
    return this->controller;
}

/*
  Disconnects from the previous controller (if it had one) and
  connects to the new controller.
 */
void BaseView::setController(BaseController *controller)
{
    if (this->controller) {
        disconnect(controller, SIGNAL(update(QList<BaseModel*>)), this, SLOT(onDataUpdate(QList<BaseModel*>)));
    }

    this->controller = controller;
    connect(controller, SIGNAL(update(QList<BaseModel*>)), this, SLOT(onDataUpdate(QList<BaseModel*>)));
}


/*
  BaseView needs to know the current set of models being displayed, so double-click
  handlers will work properly.

  This *must* be called by overrides of this method.
  */
void BaseView::onDataUpdate(QList<BaseModel *> models)
{
    this->models = models;
}

/*
  Converts a QModelIndex, from ShinyList's doubleClicked signal, into a
  BaseModel *.
 */
void BaseView::onShinyListDoubleClicked(QModelIndex index)
{
    int row = index.row();
    int len = models.length();

    // Show an informative error message if we find out that
    // BaseView::onDataUpdate() wasn't being called by an inheriting class
    if (len == 0) {
        qDebug() << "\n";
        qDebug() << "!!!!! BaseView: FATAL: models.length() == 0";
        qDebug() << "!!!!! Inheriting class's onDataUpdate() implementation may have failed"
                    " to call BaseView's implementation.";
        qDebug() << "Crashing in 3, 2, 1...\n";
    }

    BaseModel *model = models.at(row);
    emit detailsRequested(model);
}

/*
  Creates the filter components, located at the top of each view.

  To init the widgets in that area (for signals & slots, changing
  text, etc), override this method and remember to call this
  implementation at the start of the overriding method.
 */
QHBoxLayout *BaseView::createFilterComponents()
{
    filterLayout = new QHBoxLayout;

    reportsButton = new QPushButton("Reports...");
    filterLayout->addWidget(reportsButton);

    filterSeparator = new SeparatorWidget;
    filterSeparator->setVertical();
    filterLayout->addWidget(filterSeparator);

    filterEdit = new QLineEdit;
    filterEdit->setPlaceholderText("Search");
    filterLayout->addWidget(filterEdit);

    filterBox = new QComboBox;
    filterBox->addItem("Search all fields", "ALL");
    filterBox->addItem("Search by name", "NAME");
    filterLayout->addWidget(filterBox);

    return filterLayout;
}

/*
  Creates a button at the bottom of the view.

  If you wish to add more buttons, reimplement this method, and
  don't call the superclass implementation (i.e. this one) as it
  will be useless to you.

  If you only wish to init the widgets in that area (for signals
  & slots, changing text, etc), override this method and remember
  to call this implementation at the start of the overriding method.
 */
QHBoxLayout *BaseView::createBottomComponents()
{
    buttonLayout = new QHBoxLayout;
    addButton = new QPushButton;

    buttonLayout->addStretch();
    buttonLayout->addWidget(addButton);
    buttonLayout->addStretch();

    return buttonLayout;
}


/*
  Creates the UI components of the view.

  When implementing your own view, you will most likely want
  to override this method, and initialize your widgets from
  there. To do so, call this implementation, then proceed to
  initializing the widgets.
 */
void BaseView::initViewComponents()
{
    qDebug() << "BaseView::initUiComponents() called";
    mainLayout = new QVBoxLayout;

    topLabel = new QLabel;
    topLabel->hide();
    mainLayout->addWidget(topLabel);

    QHBoxLayout *filterLayout = this->createFilterComponents();
    mainLayout->addLayout(filterLayout);

    slist = new ShinyList;
    mainLayout->addWidget(slist);

    buttonLayout = this->createBottomComponents();
    mainLayout->addLayout(buttonLayout);

    this->setLayout(mainLayout);
}

/*
  Initializes the signals and slots for the abstracted handling of
  double-clicks of the view's ShinyList.

  When implementing a view, you DEFINITELY want to override this
  method, making sure that you call this implementation. Otherwise,
  double-clicks to the ShinyList will not trigger the convenient
  detailsRequested signal.
 */
void BaseView::initViewSignalsAndSlots()
{
    connect(this->slist, SIGNAL(doubleClicked(QModelIndex)),
            this, SLOT(onShinyListDoubleClicked(QModelIndex)));
}

/*
  Hides the "Reports..." button and the separator separating it from the
  search box. Used for views that do not have reports.
 */
void BaseView::hideReportsWidgets()
{
    this->reportsButton->hide();
    this->filterSeparator->hide();
}

BaseView::BaseView(QWidget *parent) :
    QWidget(parent)
{
    this->controller = NULL;

    // The inheriting classes should be the ones to call initUiComponents()
}
